package team.bluepen.supermarket.data.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import space.lingu.light.DataColumn;
import space.lingu.light.DataTable;
import team.bluepen.supermarket.kafka.KafkaDeserializer;
import team.bluepen.supermarket.kafka.KafkaSerializer;

import java.beans.ConstructorProperties;
import java.io.Serializable;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * @author RollW
 */
@DataTable(name = "product")
public class Product implements Serializable {
    @JsonProperty("userId")
    @DataColumn(name = "user_id")
    private final long userId;

    @JsonProperty("id")
    @DataColumn(name = "id")
    private final long id;

    @JsonProperty("name")
    @DataColumn(name = "name")
    private final String name;

    @JsonProperty("amount")
    @DataColumn(name = "amount")
    private final int amount;

    @JsonProperty("price")
    @DataColumn(name = "price")
    private final int price;

    @JsonProperty("state")
    @DataColumn(name = "state")
    private final boolean state;

    @ConstructorProperties({"userId", "id", "name", "amount", "price", "state"})
    public Product(long userId, long id, String name,
                    int amount, int price, boolean state) {
        this.userId = userId;
        this.id = id;
        this.name = name;
        this.amount = amount;
        this.price = price;
        this.state = state;
    }

    public long getUserId() {
        return userId;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAmount() {
        return amount;
    }

    public int getPrice() {
        return price;
    }

    public boolean isState() {
        return state;
    }

    public Builder toBuilder() {
        return new Builder(this);
    }

    public static Builder builder() {
        return new Builder();
    }

    public String serialize() {
        return String.format("%s\t%s\t%s\t%s\t%s\t%s", userId,
                id, name, amount, price, state);
    }

    public static Product deserialize(String value) {
        String[] strings = value.split(Pattern.quote("\t"));
        return new Product(
                Long.parseLong(strings[0]),
                Long.parseLong(strings[1]),
                strings[2],
                Integer.parseInt(strings[3]),
                Integer.parseInt(strings[4]),
                Boolean.parseBoolean(strings[5]));
    }

    public static KafkaSerializer<Product> serializer() {
        return Product.Serial.INSTANCE;
    }

    public static KafkaDeserializer<Product> deserializer() {
        return Product.Serial.INSTANCE;
    }

    @Override
    public String toString() {
        return "Product{" +
                "userId=" + userId +
                ", id=" + id +
                ", name='" + name + '\'' +
                ", amount=" + amount +
                ", price=" + price +
                ", state=" + state +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Product product = (Product) o;
        return userId == product.userId && id == product.id && amount == product.amount && price == product.price && state == product.state && Objects.equals(name, product.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, id, name, amount, price, state);
    }

    private static class Serial implements KafkaDeserializer<Product>, KafkaSerializer<Product> {

        @Override
        public Product deserialize(String data) {
            return Product.deserialize(data);
        }

        @Override
        public String serialize(Product product) {
            return product.serialize();
        }

        static final Serial INSTANCE = new Serial();
    }

    public static class Builder {
        private long userId;
        private long id;
        private String name;
        private int amount;
        private int price;
        private boolean state;

        public Builder() {
        }

        public Builder(Product product) {
            if (product == null) {
                throw new NullPointerException();
            }
            this.userId = product.userId;
            this.id = product.id;
            this.name = product.name;
            this.amount = product.amount;
            this.price = product.price;
            this.state = product.state;
        }

        public Builder setUserId(long userId) {
            this.userId = userId;
            return this;
        }

        public Builder setId(long id) {
            this.id = id;
            return this;
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setAmount(int amount) {
            this.amount = amount;
            return this;
        }

        public Builder setPrice(int price) {
            this.price = price;
            return this;
        }

        public Builder setState(boolean state) {
            this.state = state;
            return this;
        }

        public Product build() {
            return new Product(userId, id, name, amount, price, state);
        }
    }

}
